Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 7f868c6c28806f7b3187171108ebec8b307e4bf8


Parents : 9ea2a58
Author : Mark Qvist <mark@unsigned.io>
Date : 2025-11-22T14:19:23+01:00

Added interference display to waterfall. Improved Heltec V4 false interference rejection.

Changes

4 files changed, 33 insertions(+), 10 deletions(-)

M Boards.h +2
M Config.h +1 -1
M Display.h +13 -1

Diff

diff --git a/Boards.h b/Boards.h
index eaee2d5..ef2b8c5 100644
--- a/Boards.h
+++ b/Boards.h
@@ -417,6 +417,8 @@
const int pin_tcxo_enable = -1;
#define HAS_BUSY true
#define DIO2_AS_RF_SWITCH true
+ #define LNA_GD_THRSHLD (-109)
+ #define LNA_GD_LIMIT (-89)
#define LORA_LNA_GAIN 17
#define LORA_LNA_GVT 12

diff --git a/Config.h b/Config.h
index 2ada4a7..dec0063 100644
--- a/Config.h
+++ b/Config.h
@@ -151,7 +151,7 @@
uint8_t model = 0x00;
uint8_t hwrev = 0x00;
- #define NOISE_FLOOR_SAMPLES 64
+ #define NOISE_FLOOR_SAMPLES 128
int noise_floor = -292;
int current_rssi = -292;
int last_rssi = -292;

diff --git a/Display.h b/Display.h
index 59c5133..7d903b9 100644
--- a/Display.h
+++ b/Display.h
@@ -152,6 +152,7 @@ bool device_firmware_ok();
#define WATERFALL_SIZE 46
int waterfall[WATERFALL_SIZE];
+int waterfall_meta[WATERFALL_SIZE];
int waterfall_head = 0;
int p_ad_x = 0;
@@ -722,6 +723,9 @@ void draw_signal_bars(int px, int py) {
#define WF_RSSI_MIN -135
#define WF_RSSI_SPAN (WF_RSSI_MAX-WF_RSSI_MIN)
#define WF_PIXEL_WIDTH 10
+#define WF_M_RX 0x00
+#define WF_M_TX 0x01
+#define WF_M_NTFR 0x02
void draw_waterfall(int px, int py) {
int rssi_val = current_rssi;
if (rssi_val < WF_RSSI_MIN) rssi_val = WF_RSSI_MIN;
@@ -729,11 +733,14 @@ void draw_waterfall(int px, int py) {
int rssi_normalised = ((rssi_val - WF_RSSI_MIN)*(1.0/WF_RSSI_SPAN))*WF_PIXEL_WIDTH;
if (display_tx) {
for (uint8_t i = 0; i < WF_TX_SIZE; i++) {
+ waterfall_meta[waterfall_head] = WF_M_TX;
waterfall[waterfall_head++] = -1;
if (waterfall_head >= WATERFALL_SIZE) waterfall_head = 0;
}
display_tx = false;
} else {
+ if (interference_detected) { waterfall_meta[waterfall_head] = WF_M_NTFR; }
+ else { waterfall_meta[waterfall_head] = WF_M_RX; }
waterfall[waterfall_head++] = rssi_normalised;
if (waterfall_head >= WATERFALL_SIZE) waterfall_head = 0;
}
@@ -742,8 +749,13 @@ void draw_waterfall(int px, int py) {
for (int i = 0; i < WATERFALL_SIZE; i++){
int wi = (waterfall_head+i)%WATERFALL_SIZE;
int ws = waterfall[wi];
+ int wm = waterfall_meta[wi];
if (ws > 0) {
- stat_area.drawLine(px, py+i, px+ws-1, py+i, SSD1306_WHITE);
+ if (wm == WF_M_RX) { stat_area.drawLine(px, py+i, px+ws-1, py+i, SSD1306_WHITE); }
+ else if (wm == WF_M_NTFR) {
+ uint8_t o = 0;
+ for (uint8_t ti = 0; ti < WF_PIXEL_WIDTH/2; ti++) { stat_area.drawPixel(px+ti*2+o, py+i, SSD1306_WHITE); }
+ }
} else if (ws == -1) {
uint8_t o = i%2;
for (uint8_t ti = 0; ti < WF_PIXEL_WIDTH/2; ti++) {

diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino
index 5d2eb6a..5649206 100644
--- a/RNode_Firmware.ino
+++ b/RNode_Firmware.ino
@@ -1358,20 +1358,26 @@ int noise_floor_buffer[NOISE_FLOOR_SAMPLES] = {0};
void update_noise_floor() {
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
if (!dcd) {
+ #if BOARD_MODEL != BOARD_HELTEC32_V4
if (!noise_floor_sampled || current_rssi < noise_floor + CSMA_INFR_THRESHOLD_DB) {
+ #else
+ if ((!noise_floor_sampled || current_rssi < noise_floor + CSMA_INFR_THRESHOLD_DB) || (noise_floor_sampled && (noise_floor < LNA_GD_THRSHLD && current_rssi <= LNA_GD_LIMIT))) {
+ #endif
#if HAS_LORA_LNA
// Discard invalid samples due to gain variance
// during LoRa LNA re-calibration
if (current_rssi < noise_floor-LORA_LNA_GVT) { return; }
#endif
+ bool sum_noise_floor = false;
noise_floor_buffer[noise_floor_sample] = current_rssi;
noise_floor_sample = noise_floor_sample+1;
if (noise_floor_sample >= NOISE_FLOOR_SAMPLES) {
noise_floor_sample %= NOISE_FLOOR_SAMPLES;
noise_floor_sampled = true;
+ sum_noise_floor = true;
}
- if (noise_floor_sampled) {
+ if (noise_floor_sampled && sum_noise_floor) {
noise_floor = 0;
for (int ni = 0; ni < NOISE_FLOOR_SAMPLES; ni++) { noise_floor += noise_floor_buffer[ni]; }
noise_floor /= NOISE_FLOOR_SAMPLES;
@@ -1402,7 +1408,13 @@ void update_modem_status() {
portEXIT_CRITICAL();
#endif
- interference_detected = !carrier_detected && (current_rssi > (noise_floor+CSMA_INFR_THRESHOLD_DB));
+ #if BOARD_MODEL == BOARD_HELTEC32_V4
+ if (noise_floor > LNA_GD_THRSHLD) { interference_detected = !carrier_detected && (current_rssi > (noise_floor+CSMA_INFR_THRESHOLD_DB)); }
+ else { interference_detected = !carrier_detected && (current_rssi > LNA_GD_LIMIT); }
+ #else
+ interference_detected = !carrier_detected && (current_rssi > (noise_floor+CSMA_INFR_THRESHOLD_DB));
+ #endif
+
if (interference_detected) { if (led_id_filter < LED_ID_TRIG) { led_id_filter += 1; } }
else { if (led_id_filter > 0) {led_id_filter -= 1; } }
@@ -1410,14 +1422,11 @@ void update_modem_status() {
// LNA recalibration, antenna swap, moving into new RF
// environment or similar.
if (interference_detected && current_rssi < CSMA_RFENV_RECAL_LIMIT_DB) {
- if (!interference_persists) {
- interference_persists = true; interference_start = millis();
- } else {
+ if (!interference_persists) { interference_persists = true; interference_start = millis(); }
+ else {
if (millis()-interference_start >= CSMA_RFENV_RECAL_MS) { noise_floor_sampled = false; interference_persists = false; }
}
- } else {
- interference_persists = false;
- }
+ } else { interference_persists = false; }
if (carrier_detected) { dcd = true; } else { dcd = false; }


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────